test

11.4 JRCMD命令参考

为便于使用,本节中的命令按字母顺便编排,若该命令只在JRockit R27或R28的某个版本得到支持,则会在标题旁注明版本信息,否则表示这两个版本均支持该命令。

11.4.1 check_flightrecording (R28)

在JRockit R27中,与该命令相对应的是checkjrarecording。该命令用于检查JFR引擎的状态,更多有关JFR的内容,请参见第8章第9章的内容。一般情况下,该命令至少会返回一条当前正在进行的记录任务,因为大部分版本的R28在运行的时候都会开启一个低消耗的记录人物。由于JRockit JVM中可能同时存在多个正在执行的记录任务,因此可以为该命令指定一个任务ID,以便获取目标任务的执行状态。如果不指定参数,或者参数值为-1,则会返回所有正在执行的任务的状态。除了指定任务ID外,还可以通过参数name来指定记录任务的名字。如果是持续型记录任务,可以将参数name设置为continuous里查找。

例如:

C:\>jrcmd 6328 check_flightrecording name=continuous verbose=true
6328:
Recording : id=0 name="continuous" duration=0s (running)
http://www.oracle.com/jrockit/jvm/:
java/alloc/accumulated/thread : disabled period=1000
java/alloc/accumulated/total : enabled period=0
java/alloc/object/in_new_tla : disabled threshold=10000000
java/alloc/object/outside_tla : disabled threshold=10000000
java/exception/stats : enabled period=1000
java/exception/throw : disabled period=1000
java/file/read : disabled threshold=10000000
java/file/write : disabled threshold=10000000
java/monitor/enter : disabled threshold=10000000
java/monitor/profile : disabled period=1000
java/monitor/wait : disabled threshold=10000000
java/socket/read : disabled threshold=10000000
java/socket/write : disabled threshold=10000000
java/thread/end : enabled period=0
java/thread/park : disabled threshold=10000000
java/thread/sleep : disabled threshold=10000000
java/thread/start : enabled period=0
vm/class/load : disabled threshold=10000000
vm/class/memory/free : enabled threshold=0

如果将参数verbose的值设为false,则只会在简单列出记录任务的ID、名字和持续时间;而设为true后,则会像示例一样,列出记录任务的事件生产者,以及每个事件生产者的的事件类型。上面的示例中列出了激活的持续型记录,其ID为0。在http://www.oracle.com/jrockit/jvm/中列出了各种类型的事件生产者,可以作为参考。

译者注,链接已死。

参见start_flightrecording stop_flightrecordingdump_flightrecording命令的说明。

11.4.2 checkjrarecording (R28)

该命令通常与startjrarecording命令一起使用,用于检查JRockit JVM中是否已经存在正在执行中的记录任务。若是JRA中已经有记录任务正在执行,则会列出该任务的设置参数。下面的示例是启动JRA记录任务9秒钟之后的执行checkjrarecording命令的结果:

C:\>jrcmd 5516 checkjrarecording
5516:
JRA is running a recording with the following options:
filename=D:\myrecording.jra, recordingtime=120s, methodsampling=1,
gcsampling=1, heapstats=1, nativesamples=0, methodtraces=1,
sampletime=5,zip=1, hwsampling=0, delay=0s, tracedepth=64
threaddump=1, threaddumpinterval=0s, latency=1,
latencythreshold=20ms, cpusamples=1, cpusampleinterval=1s
The recording was started 9 seconds ago.
There are 111 seconds left of the recording.

上面示例中的记录任务是通过startjrarecording命令启动的。

参见startjrarecordingstopjrarecording命令的说明。

译者注,stopjrarecording命令在本书中并未找到相关说明内容,https://community.oracle.com/thread/690864?start=0&tstart=0和JRocki JRCMD中有简单的说明,请自取。

11.4.3 command_line

有时候,需要检查JRockit JVM的启动设置。比如,当JVM的垃圾回收器行为比较奇怪时,可以使用该命令来检查相关的参数配置,又或者使用该命令查看随JVM一起启动的代理(agent)的配置。

该命令会列出JVM的启动参数,只不过在这里列出的是实际传递给JVM的参数,以及那些隐式传给JVM的参数。如下所示:

C:\>jrcmd 2416 command_line
2416:
Command Line: -Denv.class.path=.;C:\Program Files\
  Java\jre6\lib\ext\QTJava.zip -Dapplication.home=C:\jrockits\R28.0.0_
  R28.0.0-547_1.6.0 -client -Djrockit.ctrlbreak.enableforce_crash=true
  -Dsun.java.launcher=SUN_STANDARD com.jrockit.mc.rcp.start.MCMain
  -Xmx512m -Xms64m -Xmanagement:port=4712,ssl=false,authenticate=false

11.4.4 dump_flightrecording (R28)

该命令用于在不中断记录任务的情况下,获取记录内容,因而可以获取持续性记录任务的内容。其基本实现是,克隆目标任务,暂停该克隆后的记录任务,再将之写入到硬盘中。

如用方式如下所示:

C:\>jrcmd 7420 dump_flightrecording recording=0
  copy_to_file=my_continuous_snapshot.jfr.gz compress_copy=true

在上面的示例中,通过命令指示JRCMD完成对编号为0的记录任务进行转储为本地文件my_continous_snapshot.jfr.gz。一般情况下,编号为0的是持续性记录任务,会一直在JVM中运行。当然,也可以通过参数name来指定要转储的记录任务,例如name=continuous。设置参数compress_copy为true时,会将转储文件以gzip进行压缩。

参见startjrarecording stopjrarecordingcheck_flightrecording命令的说明。

11.4.5 heap_diagnostics (R28)

heap_diagnostics命令用于获取JVM中堆的详细信息,包括内存使用情况和引用对象使用情况等信息。执行该命令时,会触发一次full gc来收集相关信息。该命令不接受其他参数。

输出信息包含3个部分。

第一部分是系统信息,包括可用内存总量和堆内存总量。如下所示:

C:\>jrcmd 7420 heap_diagnostics
7420:
Invoked from diagnosticcommand
======== BEGIN OF HEAPDIAGNOSTIC =========================

Total memory in system: 3706712064 bytes
Available physical memory in system: 1484275712 bytes
-Xmx (maximal heap size) is 1073741824 bytes
Heapsize: 65929216 bytes
Free heap-memory: 8571400 bytes

第2部分是 Detailed Heap Statistics,基本上与print_object_summary命令的输出相同,但不包含 points-to信息。这里会列出系统中所有类型的相关信息,因此输出内容会很长:

  • 第一列是当前类型的实例所占用的堆内存的百分比;
  • 第二列是当前类型的实例所占用的堆内存的大小,单位为KB;
  • 第三列是当前类型的存活实例的数量
  • 第四列是自上一次调用heap_diagnostics命令后,当前类型的实例占用堆内存大小的变化值,单位为KB;
  • 第五列是类型名。

    --------- Detailed Heap Statistics: --------- 25.9% 3179k 37989 +0k [C 9.6% 1178k 2210 +0k [I 7.4% 912k 38943 +0k java/lang/String 7.4% 906k 265 +0k [B 6.2% 764k 6994 +0k java/lang/Class ...

      12257kB total ---
    

    --------- End of Detailed Heap Statistics ---

第3部分是引用对象统计信息(Reference Object statistics),即引用对象使用情况的详细信息,例如弱引用。引用对象信息也是按照类型进行划分的,在每种类型下,列出了当前类型实例所指向的其他类型。如下所示:

  • 第一列是实例的数量。
  • 第二列是处于可达(reachable)状态的实例的数量。
  • 第三列是处于不可达(unreachable)状态的实例的数量。
  • 第四列是在本轮GC中处于活动(active)状态的引用对象的数量。
  • 第五列是在本轮GC之前,处于活动(active)状态的引用对象的数量。如果引用对象被放入到引用队列中,则它们可能会在引用队列中待一段时间,直到被移除引用队列。
  • 第六列是指向null的实例的实例的数量。
  • 第七列和最后一列是引用对象所指向的类型。

    ----- Reference Objects statistics separated per class -----

      Total Reach Act PrevAct Null
      ----- ----- --- ------- ----
    

    Soft References:

      637 81  0   4   552     Total for all Soft References 
    

    java/lang/ref/SoftReference =>

      559 7   0   0   552 Total
      552 0   0   0   552 =>  null
      2   2   0   0   0   =>  [Ljava/lang/reflect/Constructor;
      1   1   0   0   0   =>  org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader
      1   1   0   0   0   =>  [Ljava/lang/String;
      1   1   0   0   0   =>  java/util/jar/Manifest
      1   1   0   0   0   =>  java/lang/StringCoding$StringDecoder
      1   1   0   0   0   =>  sun/font/FileFontStrike
    

    java/util/ResourceBundle$BundleReference =>

      44  42  0   2   0   Total
      31  31  0   0   0   =>  java/util/ResourceBundle$1
      11  11  0   0   0   =>  java/util/PropertyResourceBundle
      2   0   0   2   0   =>  null
    

    org/eclipse/core/internal/registry/ReferenceMap$SoftRef =>

      21  20  0   1   0   Total
      20  20  0   0   0   =>
    org/eclipse/osgi/framework/internal/core/BundleHost
      1   0   0   1   0   => null
    

    sun/misc/SoftCache$ValueCell =>

      1   0   0   1   0   Total
      1   0   0   1   0   =>  null
    

    Weak References:

      3084 2607 0 236 241 Total for all Weak References
    

    java/lang/ref/WeakReference =>

      1704    1463    0   0   241 Total
      765     765     0   0   0   => java/lang/String
      330     330     0   0   0   => java/lang/Class
      241     0       0   0   241 => null
    

    Phantom References:

      6   6   0   0   0   Total for all Phantom References
    

    java/lang/ref/PhantomReference =>

      6   6   0   0   0   Total
      5   5   0   0   0   =>  java/lang/Object
      1   1   0   0   0   =>  sun/dc/pr/Rasterizer
    

    Cleared Phantom:

      9   9   0   0   0   Total for all Cleared Phantom
    

    jrockit/vm/ObjectMonitor =>

      9   9   0   0   0   Total
      2   2   0   0   0   =>
    org/eclipse/osgi/framework/eventmgr/EventManager$EventThread
      1   1   0   0   0   => java/util/TaskQueue
    

    Finalizers:

      197 197 0   0   0   Total for all Finalizers
      88  88  0   0   0   =>  java/util/zip/ZipFile
      55  55  0   0   0   =>  java/util/zip/Inflater
      18  18  0   0   0   =>  java/awt/Font
      14  14  0   0   0   =>  java/lang/ClassLoader$NativeLibrary
    

    Weak Handles:

      12309   12309   0   0   0   Total for all Weak Handles
      9476    9476    0   0   0   =>
    org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader
      1850    1850    0   0   0   =>  java/lang/String
    

    Soft reachable referents not used for at least 198.332 s cleared. 4 SoftReferences were soft alive but not reachable

    (when found by the GC),
    0 were both soft alive and reachable, and 633 were not soft alive.
    

    ----- End of Reference Objects statistics ----- ======== END OF HEAPDIAGNOSTIC ==========================

从这个示例中可以看到,大部分弱引用对象都指向String类的实例。弱引用对象是指由java.lang.ref.WeakReference实例引用的对象。在示例中系统中,共有3084个弱引用,其中2067个处于可达状态。另外,在示例中可以看到,软引用对象指向的对象至少存活了198秒。

对于粗粒度的对象引用分析和堆使用率分析来说,heap_diagnostics命令是非常有用的。当然,使用JFR或Memleak Tool可以更简便的实现同样功能。

参见print_object_summary命令的说明。

11.4.6 hprofdump (R28)

有时候,需要将堆内存转储到本地文件以便做离线分析。到JRockit R28版本时,JRockit可以生成HPROF格式的堆转储文件,这样就可以使用其他支持HPROF格式的工具(例如Eclipse Memory Analyzer Tool)做离线分析了。

使用方式如下所示:

C:\>jrcmd 7772 hprofdump filename=mydump.hprof
  segment_threshold=2G segment_size=1G
7772:
Wrote dump to mydump.hprof

译者注:HRPOF的介绍,参见https://docs.oracle.com/javase/7/docs/technotes/samples/hprof.html

使用参数segment_thresholdsegment_size可以将转储文件分割为几个较小的文件。在上面的示例中,当JVM堆超过2G时,会以1G为大小分割为多个转储文件。

注意,只有在工具支持Java PROFILE 1.0.2 HPROF格式的转储文件时,才能使用参数segment_sizesegment_threshold

生成的转储文件会放到JROCKIT_HOME目录下,如果不指定文件名的话,会以时间戳来命名文件,如下所示:

C:\>jrcmd 7772 hprofdump
7772:
Wrote dump to heapdump_Tue_Sep_22_19_09_16_2009

参见命令memleakserveroom_diagnostics

11.4.7 kill_management_server

该命令用于关闭外部管理服务器(exter management server)。曾经,因为存在一些问题,导致以"stop"开头的命令会终止对 ctrlhandler.act文件的解析,于是就没有将关闭管理服务器的命令命名为 "stop_management_server""。

使用该命令时无需添加额外的参数,如下所示:

C:\>jrcmd 7772 kill_management_server
7772:

参见start_management_server命令。

11.4.8 list_vmflags (R28)

某些JVM参数可以通过类似–XX:<Flag>=<value>的形式来设置。在第1章中曾经介绍过,这里参数成为VM参数,可以通过命令list_vmflags列出这些参数。

如下所示:

C:\>jrcmd 7772 list_vmflags describe=true alias=true
Global:
  UnlockDiagnosticVMOptions = false (default, writeable)
    - Enable processing of flags relating to field diagnostics
UnlockInternalVMOptions = false (default)
    - Enable processing of internal, unsupported flags
Class:
  FailOverToOldVerifier = true (default, writeable)
    - Fail over to old verifier when split verifier fails
  UseVerifierClassCache = true (default)
    - Try to cache java.lang.Class lookups for old verifier.
  UseClassGC = true (default)
    (Alias: -Xnoclassgc)
    - Allow GC of Java classes
...
Threads:
  UseThreadPriorities = false (default)
    - Use native thread priorities
  DeferThrSuspendLoopCount = 4000 (default, writeable)
    - Number of iterations in safepoint loop until we try blocking
...

由于VM参数非常多,因此在上面的示例中只列出了其中的一部分,其中某些VM参数是可以在运行过程中通过set_vmflag命令动态设置,而另外一些则只能在启动时设置。

对于高端用户来说,可以在启动JVM时,设置参数-XX:UnlockInternalVMOptions=true以开启对JVM内存参数的访问。不过,风险自负。

参见set_vmflag命令。

11.4.9 lockprofile_print

只有当JVM开启了锁分析(使用JVM参数-XX:UseLockProfiling=true-XX:UseNativeLockProfiling=true,参见第4章的相关内容)时,该命令才会生效,它会打印出锁分析的相关内容。

C:\>jrcmd 1442 lockprofile_print
1442:
Class, Lazy Banned, Thin Uncontended, Thin Contended, Lazy Reservation,
  Lazy lock, Lazy Reverted, Lazy Coop-Reverted, Thin Recursive, Fat
  Uncontended, Fat Contended, Fat Recursive, Fat Contended Sleep,
  Reserve Bit Uncontended, Reserve Bit Contended
[B, false, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
java/lang/Thread, false, 11, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
java/security/Permissions, false, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0
java/util/Hashtable, false, 0, 0, 34, 524, 1, 0, 0, 0, 0, 0, 0, 0, 0
java/lang/Class, false, 0, 0, 24, 77, 2, 0, 0, 0, 0, 0, 0, 0, 0
java/lang/Object, false, 1, 0, 11, 139572, 1, 0, 0, 1, 0, 0, 0, 6, 0
java/lang/StringBuffer, false, 0, 0, 137, 773, 0, 0, 0, 0, 0, 0, 0, 0, 0
sun/nio/cs/StandardCharsets,
  false, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
java/util/Properties, false, 0, 0, 5, 479, 0, 0, 0, 0, 0, 0, 0, 0, 0
java/lang/ThreadGroup, false, 0, 0, 3, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0
java/lang/ref/Reference$ReferenceHandler,
  false, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
sun/security/provider/Sun,
  false, 0, 0, 39, 5589, 0, 0, 0, 0, 0, 0, 0, 0, 0
java/io/PrintStream, false, 0, 0, 7, 7818, 0, 0, 0, 0, 0, 0, 0, 0, 0
java/net/URL, false, 0, 0, 70, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0
java/io/ByteArrayInputStream,
  false, 0, 0, 47, 1115, 0, 0, 0, 0, 0, 0, 0, 0, 0
java/util/logging/Logger, false, 0, 0, 2, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0
jrockit/vm/CharBufferThreadLocal,
  false, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0
java/security/Provider$Service,
  false, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
java/lang/Runtime, false, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
java/lang/reflect/Field, false, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0
java/util/Random, false, 0, 0, 6, 18556549, 1, 0, 0, 0, 0, 0, 0, 0, 0

参见lockprofile_reset命令。

11.4.10 lockprofile_reset

只有当JVM开启了锁分析(使用JVM参数-XX:UseLockProfiling=true-XX:UseNativeLockProfiling=true,参见第4章的相关内容)时,该命令才会生效,它会重置当前锁分析计数器的值为0。

参见lockprofile_print命令。

11.4.11 memleakserver

该命令用于启动/关闭 Memory Leak Server(MLS)。JRockit Meomory Leak Detector使用MLS作为本地服务器来通信。正常情况下,MLS会通过JMX自行启动,但某些情况下,不得不手动开启MLS。例如,可能只想启动MLS,而不启动JMX代理(JMX agent),此时就可以使用memleakserver命令来控制MLS的生命周期,其就像一个开关一样,再执行一次就可以关闭MLS。

The following example starts the MLS on port 7899: 下面的命令在开启MLS时,指定端口为7899:

C:\>jrcmd 5516 memleakserver port=7899
5516:
Memleak started at port 7899.

再执行一次,MLS就会关闭:

C:\>jrcmd 5516 memleakserver port=7899
5516:
Stopping the server does not produce any output.

参见hprofdump命令。

11.4.12 oom_diagnostics (R27)

该命令是JRockit R28版本中heap_diagnostics命令的别名

参见heap_diagnostics

11.4.13 print_class_summary

有时候,需要查看JVM是否载入了某个类。例如,某个SPI框架使用了动态类载入功能,当它执行失败时,需要查找出某些类是否已经被载入过了。其中一种方案是转储出所有已载入的类,然后使用grep命令来查找指定的类。使用print_class_summary命令就可以很方便的转储出所有的类。如下所示:

C:\>jrcmd 5516 print_class_summary
5516:
  - Class Summary Information starts here
class java/lang/Object
*class java/util/Vector$1
*class sun/util/calendar/CalendarUtils
*class sun/util/calendar/ZoneInfoFile$1
*class sun/util/calendar/ZoneInfoFile
*class sun/util/calendar/TzIDOldMapping
*class java/util/TimeZone$1
*class java/util/TimeZone
**class java/util/SimpleTimeZone
**class sun/util/calendar/ZoneInfo
*class sun/util/calendar/CalendarDate
**class sun/util/calendar/BaseCalendar$Date
***class sun/util/calendar/Gregorian$Date
*class sun/util/calendar/CalendarSystem
**class sun/util/calendar/AbstractCalendar
***class sun/util/calendar/BaseCalendar
****class sun/util/calendar/Gregorian
...

在上面的示例中,输出的类是按照各自的继承关系来排序,并使用星号来标识继承深度。下面的示例则展示了在类Unix系统上如何查找具体的类型:

$ jrcmd 5516 print_class_summary | grep LoadAnd
*class LoadAndDeadlock
**class LoadAndDeadlock$LockerThread
**class LoadAndDeadlock$AllocThread

11.4.14 print_codegen_list

该命令用于显示代码生成队列的长度和当前JVM中的优化队列。使用参数list来控制是否显示队列的内容。如下所示:

C:\>jrcmd 1442 print_codegen_list list=true
1442:
-------------------------------------------------------
        format: <position> <directive no> <method description>
        strategies: q=quick, n=normal, o=optimize
          JIT queue: 0 methods in queue
          OPT queue:
0: 1 java/math/BigDecimal.<init>(Ljava/math/BigInteger;JII)V
1: 1 java/math/BigDecimal.add(Ljava/math/BigDecimal;)Ljava/math/BigDecimal;
2: 1 java/lang/String.<init>([C)V
3: 1 java/util/TreeMap$NavigableSubMap.size()I
4: 1 java/util/TreeMap$NavigableSubMap.setLastKey()V
5: 1 jrockit/vm/Strings.compare(Ljava/lang/String;Ljava/lang/String;)I
6: 1 com/sun/org/apache/xerces/internal/dom/CharacterDataImpl.setNodeValueInternal(Ljava/lang/String;Z)V
7: 1 com/sun/org/apache/xerces/internal/dom/CoreDocumentImpl.changed()V
8: 1 java/lang/String.getChars(II[CI)V
9: 1 com/sun/org/apache/xerces/internal/dom/NodeImpl.appendChild(Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node;
10: 1 spec/jbb/Warehouse.getAddress()Lspec/jbb/Address;
11: 1 jrockit/vm/ArrayCopy.copy_checks_done2(Ljava/lang/Object;ILjava/lang/Object;II)V
12 methods in queue

11.4.15 print_memusage (R27)

正如之前章节中介绍的,除了Java堆之外,JRockit还将内存用于其他地方。有时候,若Java堆占用了太多内存,则JRockit则可能会没有足够的本地内存(native memory)使用。命令print_memusage可以用于查看JRockit是如何使用系统内存的。如下所示:

C:\>jrcmd 484536 print_memusage
484536:
[JRockit] memtrace is collecting data...
[JRockit] *** 0th memory utilization report
(all numbers are in kbytes)
Total mapped                        ;;;;;;;1298896
; Total in-use                       ;;;;;; 438768
;; executable                          ;;;;; 28460
;;; java code                            ;;;; 5952;     20.9%
;;;; used                                 ;;; 5647;     94.9%
;; shared modules (exec+ro+rw)         ;;;;; 35912
;; guards                                ;;;;; 528
;; readonly                            ;;;;; 25936
;; rw-memory                          ;;;;; 376392
;;; Java-heap                          ;;;; 262144;     69.6%
;;; Stacks                               ;;;; 3472;     0.9%
;;; Native-memory                      ;;;; 110775;     29.4%
;;;; java-heap-overhead                   ;;; 8206
;;;; codegen memory                        ;;; 896
;;;; classes                             ;;; 43008;     38.8%
;;;;; method bytecode                      ;; 4477
;;;;; method structs                       ;; 3895      (#83104)
;;;;; constantpool                        ;; 18759
;;;;; classblock                           ;; 1596
;;;;; class                                ;; 3041      (#8403)
;;;;; other classdata                      ;; 8280
;;;;; overhead                               ;; 34
;;;; threads                                ;;; 24;     0.0%
;;;; malloc:ed memory                    ;;; 22647;     20.4%
;;;;; codeinfo                             ;; 1231
;;;;; codeinfotrees                         ;; 429
;;;;; exceptiontables                       ;; 125
;;;;; metainfo/livemaptable                ;; 5883
;;;;; codeblock structs                       ;; 2
;;;;; constants                              ;; 14
;;;;; livemap global tables                 ;; 994
;;;;; callprof cache                          ;; 0
;;;;; paraminfo                             ;; 146      (#1979)
;;;;; strings                              ;; 8376      (#148622)
;;;;; strings(jstring)                        ;; 0
;;;;; typegraph                            ;; 2009
;;;;; interface implementor list             ;; 40
;;;;; thread contexts                        ;; 19
;;;;; jar/zip memory                       ;; 5378
;;;;; native handle memory                   ;; 19
;;;; unaccounted for memory              ;;; 36017;     32.5%;1.59
---------------------!!!

从上面的示例中可以看到,JRockit进程保留了1GB多的内存空间自用,看起来有点多,但实际上,JRockit只用了429MB。此外,Java堆已经使用了约60%的空间。

该命令的结果以树形显示,每个分配节点都有其子节点,例如"malloc:ed memory"表示JVM内部的结构,包括活动对象图(livemap),类型图(type graph)等等。最右侧的百分比数值表示当前节点占父节点的百分比。顶层节点并不计算百分比,之前提到Java堆大约已经使用了60%是手工计算得出的,即262,144/438,768 * 100 = 59.7%

该命令还可用来追踪本地内存发生的内存泄漏,例如使用JVMTI开发的本地代理中出现的内存泄漏。

11.4.16 print_memusage (R28)

与该命令的R27版本类似,print_memusage在R28版本中仍旧用于查看JRockit对内存的使用,不过在以往的基础上做了些改进。

在排查OOM问题时,该命令非常有用。正如第10章中介绍的,很多时候,内存泄漏往往是无意中持有废弃对象造成的,但有的时候,造成内存泄漏的原因可能多种多样,例如本地资源管理不善等,具体来说,可能是因为打开的java.util.zip.GZIPOutputStreams实例数量超过了限制,类载入器持有了太多的类,或第三方JNI代码中造成的内存泄漏。

例如:

C:\>jrcmd 7772 print_memusage
7772:
Total mapped                        1281284KB (reserved=1002164KB)
-               Java heap           1048576KB (reserved=932068KB)
-               GC tables             35084KB
-           Thread stacks             11520KB (#threads=27)
-           Compiled code              5696KB (used=5490KB)
-                Internal               840KB
-                      OS             67712KB
-                   Other             48048KB
-          JRockit malloc             29184KB (malloced=27359KB #275574)
-  Native memory tracking              1024KB (malloced=537KB #11)
-         Java class data             33600KB (malloced=33471KB #41208)

第一列是内存空间的名字,第二列是该内存空间所占用的内存大小,第三列是与内存空间相关的详细信息。在上面的示例中可以到,Java heap占用了内存的绝大部分空间,当然,这是正常情况。

在追踪本地内存泄漏问题是,通常需要查看内存使用量随时间的变化情况。使用参数baseline可以开启比较分析。

参数scale用于修改显示单位,默认为KB。

例如,将显示单位改为MB:

C:\>jrcmd 7772 print_memusage scale=M baseline
7772:
Total mapped                            1252MB (reserved=978MB)
-               Java heap               1024MB (reserved=910MB)
-               GC tables                 34MB
-           Thread stacks                 11MB (#threads=27)
-           Compiled code                  5MB (used=5MB)
-                Internal                  0MB
-                      OS                 66MB
-                   Other                 47MB
-          JRockit malloc                 28MB (malloced=26MB #275601)
-  Native memory tracking                  1MB (malloced=0MB #11)
-         Java class data                 32MB (malloced=32MB #41208)

参数baseline用于执行差异化分析,会显示出在基线时间之后发生的内存使用量变化。

C:\>jrcmd 7772 print_memusage scale=M
7772:
Total mapped                    1282MB +30MB (reserved=984MB +6MB)
-                Java heap      1024MB (reserved=910MB)
-                GC tables        34MB
-            Thread stacks        14MB +3MB (#threads=35 +8)
-            Compiled code         6MB +1MB (used=6MB)
-                 Internal         0MB
-                       OS        70MB +4MB
-                    Other        49MB +2MB
-           JRockit malloc        41MB +13MB (malloced=34MB +8MB #330019 +54418)
-   Native memory tracking         2MB (malloced=1MB #21 +10)
-          Java class data        38MB +6MB (malloced=38MB +6MB #48325 +7117)

从上面的示例中可以看出,在设置了baseline参数后,进程额外使用了30MB内存,其中的6MB被保留了下来。此外,多开了8个线程,JRockit也多分配了8MB内存。现在,JRockit本地堆工分配了330019字节内存,比之前增加了54418字节,因而多使用了13MB的虚拟内存。

malloc object是在JVM内部使用类似于malloc系统调用分配到的内存。例如,像下面的代码这样就会在本地堆上创建一个 malloc object对象,并增加 malloc object对象的个数。 void * foo = malloc(512); 类似的,调用free(foo)方法会将 malloc object数量减一。

若要重置baseline参数,不再进行比较的话,可以使用reset参数:

C:\>jrcmd 7772 print_memusage reset

使用参数trace_alloc_sites=1可以开启对本地内存分配点的追踪,设置参数trace_alloc_sites=0则可禁用之。若想追踪所有的本地内存分配点,包括JVM启动时的内存分配,将环境变量TRACE_ALLOC_SITES设置为1即可。

在开启分配点追踪后,会根据level参数的值来显示内存分配的详细信息。如果同时设置了baseline参数,则只会显示发生变化的内存分配点。例如:

C:\>jrcmd 5784 print_memusage level=1
5784:
Total mapped                1300092KB +25040KB (reserved=1090888KB -7496KB)
-           Java heap       1048576KB (reserved=1008068KB -11020KB)
-           GC tables         35084KB
-       Thread stacks         14336KB +3840KB (#threads=32 +9)
-       Compiled code          4928KB +1152KB (used=4774KB +1209KB)
-            Internal          1416KB +256KB
-                  OS         83040KB +2048KB
-               Other         50312KB +2448KB
-      JRockit malloc         27200KB +7424KB (malloced=25807KB +6236KB #266150 +63919)
              balance            44KB +9KB (#23 +5)
          breakpoints             9KB -8KB (#37 -255)
           breaktable             8KB +2KB (#13 +3)
            codealloc            56KB +25KB (#1037 +502)
            codeblock           143KB +39KB (#2567 +686)
             codeinfo          1224KB +351KB (#22300 +6404)
         codeinfotree           400KB +126KB (#74 +18)
             dynarray           116KB +30KB (#2058 +392)
         finalhandles             3KB +2KB (#14 +7)
            hashtable            32KB +32KB (#5 +3)
           implchange           982KB +354KB (#20920 +7556)
             javalock           279KB +266KB (#4477 +4092)
             libcache           245KB +47KB (#9473 +1840)
       libconstraints            22KB +3KB (#464 +75)
            lifecycle            14KB +4KB (#33 +9)
       livemap_system          1083KB +305KB (#25117 +5207)
       memleak_trends           544KB +544KB (#5809 +5809)
        memleakserver            96KB +96KB (#2906 +2906)
             metainfo          7669KB +1916KB (#21935 +6416)

在上面的示例中,JRockit Mission Control Memleak工具监视了命令调用,可以看到Memleak自身分配了一些本地内存。将日志级别调为4,可以看到更详细的内容:

C:\>jrcmd 5784 print_memusage level=4
5784:
Total mapped        1310708KB       +35656KB (reserved=1083664KB -14720KB)
-                   Java heap      1048576KB (reserved=1002572KB -16516KB)
-                   GC tables        35084KB
108KB
    +32KB (#27 +8)
    update_trends               memleak_trends.c: 364 592KB
    +592KB (#3612 +3612)
    update_trends               memleak_trends.c: 365 84KB
    +84KB (#3612 +3612)
    create_id_from_object       memleakserver.c: 170 25KB
    +25KB (#1 +1)
    create_id_from_classp       memleakserver.c: 217 116KB

最后,使用参数displayMap可以让print_memusage命令显示出各个JVM子系统的内存使用情况:

C:\>jrcmd 5784 print_memusage displayMap
5784:
Total mapped                    1311220KB       +36168KB (reserved=1083664KB -14720KB)
-           Java heap           1048576KB                (reserved=1002572KB -16516KB)
-           GC tables             35084KB
-       Thread stacks             14592KB        +4096KB (#threads=33 +10)
-       Compiled code              5824KB        +2048KB (used=5634KB +2069KB)
-            Internal              1160KB
-                  OS             83180KB        +2188KB
-               Other             52660KB        +4796KB
-      JRockit malloc             30464KB       +10688KB (malloced=29618KB +10047KB #302842 +100611)
-       Native memory tracking     2112KB        +1088KB (malloced=1035KB +582KB #672 +308)
-     Java class data 37568KB    +11264KB                (malloced=37537KB +11243KB #45413 +14104)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  CODE              Compiled code rwx   0x0000000007ef0000 (128KB)
...
   MSP   JRockit malloc (179/266) rw    0x0000000008150000 (64KB)
THREAD                 Stack 6952 rwx   0x0000000008d80000 (12KB)
...
   INT               TLA memcache rw    0x000000000e330000 (64KB)
  HEAP                  Java heap rw    0x0000000010040000 (46004KB)
  HEAP         Java heap reserved       0x0000000012d2d000.(1002572KB)
    OS                   *awt.dll r x   0x000000006d0b1000
...
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Lowest accessible address 00010000
Highest accessible address 7FFEFFFF
Amount free virtual memory 786016KB
    6 free vm areas in range   4KB -   8KB totalling > 24KB
    7 free vm areas in range   8KB -  16KB totalling > 76KB
   24 free vm areas in range  16KB -  32KB totalling >528KB
  281 free vm areas in range  32KB -  64KB totalling > 15MB
    3 free vm areas in range  64KB - 128KB totalling >236KB
    9 free vm areas in range 128KB - 256KB totalling > 1MB
    5 free vm areas in range 256KB - 512KB totalling > 1MB
    7 free vm areas in range 512KB -   1MB totalling > 4MB
    8 free vm areas in range   1MB -   2MB totalling > 11MB
    2 free vm areas in range   2MB -   4MB totalling > 4MB
    5 free vm areas in range   4MB -   8MB totalling > 30MB
    1 free vm areas in range   8MB -  16MB totalling > 11MB
    5 free vm areas in range  16MB -  32MB totalling >103MB
    1 free vm areas in range  32MB -  64MB totalling > 51MB
    1 free vm areas in range  64MB - 128MB totalling > 67MB
    1 free vm areas in range 128MB - 256MB totalling >135MB
    1 free vm areas in range 256MB - 512MB totalling >326MB

正如示例那样,内存块被划分为以下几类:

  • THREAD: 线程相关,例如线程栈;
  • INT: 内部使用相关,例如指针页(pointer page);
  • HEAP: JRockit中Java堆;
  • OS: 直接映射到操作系统的内存,例如第三方DLL或共享对象;
  • MSP: 内存空间,即专用的本地堆,例如JVM内部分配的本地内存;
  • GC: 垃圾回收相关,例如 live bits

11.4.17 print_object_summary

该命令用于堆中每个类型所占用的内存,因此可以将之作为一个简版的内存泄漏检测工具使用。当然,JRockit Mission Control Memory Leak Detector比该命令强大得多,但在某些场景下,使用该命令更加合适。例如,由于安全策略限制,无法开启MLS(参见第10章相关内容),此时就可以通过该命令完成相关操作。

print_object_summary命令会打印出堆中实例的直方图,按照每种类型统计其实例所占用的内存空间,以及从上一次执行命令之后实例占用内存的增量值。

C:\>jrcmd 6328 print_object_summary
6328:
--------- Detailed Heap Statistics: ---------
22.1% 2697k     34813 +2697k [C
14.3% 1744k       373 +1744k [B
14.2% 1736k      3220 +1736k [Ljava/lang/Object;
11.8% 1443k      2177 +1443k [I
 6.9%  839k     35833  +839k java/lang/String
 5.6%  682k      6240  +682k java/lang/Class
 2.6%  314k     13429  +314k java/util/HashMap$Entry
 2.0%  242k      3218  +242k [Ljava/util/HashMap$Entry;
 1.2%  149k      3185  +149k java/util/HashMap
 1.0%  126k      5406  +126k java/util/Hashtable$Entry
 0.9%  106k      2844  +106k [Ljava/lang/String;
 0.8%   98k      1396   +98k java/lang/reflect/Field
 0.5%   65k       844   +65k java/lang/reflect/Method
 0.5%   64k       190   +64k [S
        12192kB total ---

--------- End of Detailed Heap Statistics ---

The output contains one line per class that has instances on the heap. 输出内容中按照每种类型统计了内存使用的相关数据。

  • 第一列是当前类型的所有实例所占用的堆空间的百分比
  • 第二列是当前类型的所有实例所占用的堆空间的大小
  • 第三列是当前类型的所有实例的个数
  • 第四列是自从上次调用该命令之后内存占用的增量值
  • 第五列是类型名

在列出类型名时,使用的是正式的Java描述符格式。更多相关信息,请参见Java语言规范。

正常情况下,该命令只会列出占用内存0.5%以上的类型。修改参数cutoff的值可以调整输出结果,将百分比乘以1000作为参数值即可。

还可以使用print_object_summary命令玩些花样。就上面的示例来说,可以使用参数"points-to"找出到底是哪些实例指向了字符数组。最多可以指定8个不同的"points-to"参数,有时候会简单粗暴的将参数名设置为name1name8,再指定具体的参数值就可以列出指向这些类型的内存使用信息。

在下面的示例中,列出了指向字符数组和字符串的、内存占用大于0.1%的实例的内存使用信息:

C:\>jrcmd 6352 print_object_summary cutoffpointsto=100 name1=[C name2=java/lang/String

--------- Detailed Heap Statistics: ---------
42.0%   10622k  116820      +0k     [C
11.3%    2851k  121648      +0k     java/lang/String
 6.0%    1520k    3676      +0k     [Ljava/util/HashMap$Entry;
 4.1%    1033k   18906     +12k     org/eclipse/core/internal/registry/ReferenceMap$SoftRef
 3.5%     890k   38001      +0k     java/util/HashMap$Entry
 3.2%     800k    7323      +0k     java/lang/Class
 3.0%     747k   19820      +0k     [Ljava/lang/String;
 2.9%     741k   10063      +0k     [I
 2.9%     738k   15765      +0k     org/eclipse/core/internal/registry/ConfigurationElement
 2.8%     699k   15469      +0k     [Ljava/lang/Object;
 1.1%     284k     262      +0k     [B
 1.0%     241k    4411      +1k     org/eclipse/osgi/internal/resolver/ExportPackageDescriptionImpl
 0.7%     173k    7408      +0k     org/osgi/framework/Version
 0.7%     171k    3653      +0k     java/util/HashMap
 0.6%     148k     734      +0k     [Ljava/util/Hashtable$Entry;
 0.5%     129k       2      +0k     [Lorg/eclipse/core/internal/registry/ReferenceMap$IEntry;
    25273kB total ---

[C is pointed to from:
    99.6%   121713  java/lang/String
     0.2%      270  [[C

java/lang/String is pointed to from:
    37.2%    98288  [Ljava/lang/String;
    15.6%    41274  java/util/HashMap$Entry
    11.9%    31530  org/eclipse/core/internal/registry/ConfigurationElement
     7.2%    19067  [Ljava/lang/Object;
--------- End of Detailed Heap Statistics ---

从上面的示例可以看出,大部分字符数组都有被字符串对象引用的,而字符串对象又主要是被字符好对象引用的。这很正常。

该命令通常用于查看堆中实例的分布情况,此外,也可以追踪指定类型的内存使用增量信息,配置"points-to"参数更有利于查找内存泄漏问题。不过,查找内存泄漏问题,还是Memleak更加强大,具体用哪个,依赖于具体的场景。

参见See heap_diagnostics命令

11.4.18 print_properties

改命令用于输出JRockit的属性信息,包括启动JVM时的初始属性,专用于JRockit JVM的属性,以及当前系统属性。这三部分信息分开输出,,如下所示:

C:\>jrcmd 6012 print_properties
6012:
=== Initial Java properties: ===
java.vm.specification.name=Java Virtual Machine Specification
java.vm.vendor.url.bug=http://edocs.bea.com/jrockit/go2troubleshooting.html
java.home=D:\demos_3.1\jrmc_3.1\jre
java.vm.vendor.url=http://www.bea.com/
java.vm.specification.version=1.0
file.encoding=Cp1252
java.vm.info=compiled mode
...
=== End Initial Java properties ===

=== VM properties: ===
jrockit.alloc.prefetch=true
jrockit.alloc.redoprefetch=true
jrockit.vm=D:\demos_3.1\jrmc_3.1\jre\bin\jrockit\jvm.dll
jrockit.alloc.pfd=448
jrockit.alloc.pfl=64
jrockit.alloc.cs=512
jrockit.vm.dir=D:\demos_3.1\jrmc_3.1\jre\bin\jrockit
jrockit.alloc.cleartype=0
=== End VM properties ===

=== Current Java properties: ===
java.vm.vendor.url.bug=http://edocs.bea.com/
jrockit/go2troubleshooting.html
java.runtime.name=Java(TM) 2 Runtime Environment, Standard Edition
sun.boot.library.path=D:\demos_3.1\jrmc_3.1\jre\bin
java.vm.version=R27.6.3-40_o-112056-1.5.0_17-20090318-2104-windows-ia32
java.vm.vendor=BEA Systems, Inc.
java.vendor.url=http://www.bea.com/
path.separator=;
java.vm.name=BEA JRockit(R)
file.encoding.pkg=sun.io
user.country=SE
...
=== End Current Java properties ===

输出的结果中可能会包含重复属性设置,因为某些属性可能会同时存在于 initialcurrent部分的内容中。

11.4.19 print_threads

JVM堆SIGQUIT信号的默认处理就是打印线程调用栈信息。市面上有很多可以分析线程调用栈信息的工具,不过最好用的仍旧是Latency Analysis和JFR。此外,JRockit Management Console也可以做一些简单的分析工作,甚至能检测死锁。

命令的输入内容如下所示:

C:\>jrcmd 7420 print_threads
7420:
===== FULL THREAD DUMP ===============
Mon Sep 28 00:08:56 2009
Oracle JRockit(R) R28.0.0-547-121310-1.6._14-20090918-2121-windows-ia32

"Main Thread" id=1 idx=0x4 tid=7776 prio=6 alive, in native
  at org/eclipse/swt/internal/win32/OS.WaitMessage(  )Z
    (Native Method)[optimized]
  at org/eclipse/swt/widgets/Display.sleep(Display.java:4220)[inlined]
  at org/eclipse/ui/application/  WorkbenchAdvisor.eventLoopIdle
    (WorkbenchAdvisor.java:364)[optimized]
  at org/eclipse/ui/internal/Workbench.runEventLoop(Workbench.java:2385)
  at ...
    -- end of trace

"State Data Manager" id=13 idx=0x38 tid=7596
  prio=5 alive, sleeping, native_waiting, daemon
  at java/lang/Thread.sleep(J)V(NativeMethod)[optimized]
  at org/eclipse/osgi/internal/baseadaptor/StateManager.run(StateManager.java:297)
  at java/lang/Thread.run(Thread.java:619)
  at jrockit/vm/RNI.c2java(IIIII)V(Native Method)[optimized]
    -- end of trace

  ...

"JFR request timer" id=34 idx=0x84 tid=2624
  prio=5 alive, waiting, native_blocked, daemon
  -- Waiting for notification on: java/util/TaskQueue@0x1202F238[fat lock]
  at jrockit/vm/Threads.waitForNotifySignal(JLjava/lang/Object;)Z(Native Method)[optimized]
  at java/lang/Object.wait(J)V(Native Method)
  at java/lang/Object.wait(Object.java:485)
  at java/util/TimerThread.mainLoop(Timer.java:483)
  ^-- Lock released while waiting: java/util/TaskQueue@0x1202F238[fat lock]
  at java/util/TimerThread.run(Timer.java:462)
  at jrockit/vm/RNI.c2java(IIIII)V(Native Method)[optimized]
  -- end of trace
===== END OF THREAD DUMP ===============

默认情况下,该命令不会打印线程调用栈中调用本地方法的栈帧,若想输出这部分内容,需要添加参数nativestack=true。此外,若想在输出内容中加上有关java.util.concurrent包中锁实现的相关信息,需要添加参数concurrentlocks=true

11.4.20 print_utf8pool

该命令用于打印出JVM中所有的UTF-8常量,例如类名,方法和字符串常量。

下面的示例中列出了常量池中所有的URL:

$ jrcmd 3824 print_utf8pool | grep http
"http://www.w3.org/TR/xinclude": refs=2, len=29
"http://apache.org/xml/properties/internal/
  symbol-table": refs=12, len=54

其中,refs是指向该常量的引用的数目,len指的是以字节计算的常量值得长度。

11.4.21 print_vm_state

该命令用于打印JVM的状态,其格式与JRockit宕机时生成的转储文件类似。如下所示:

C:\>jrcmd 7420 print_vm_state
7420:
Uptime          : 0 days, 02:35:53 on Tue Sep 22 19:14:39 2009
Version         : Oracle JRockit(R) R28.0.0-547-121310-1.6.0_14-20090918-2121-windows-ia32
CPU             : Intel Core 2 SSE SSE2 SSE3 SSSE3 SSE4.1 Core Intel64
Number CPUs     : 2
Tot Phys Mem    : 3706712064 (3534 MB)
OS version      : Microsoft Windows Vista version 6.0 Service Pack 2(Build 6002) (32-bit)
Thread System   : Windows Threads
Java locking    : Lazy unlocking enabled (class banning) (transfer banning)
State           : JVM is running
Command Line    : -Denv.class.path=.;C:\Program Files\Java\jre6\lib\ext\QTJava.zip -Dapplication.home=C:\jrockits\R28.0.0_R28.0.0-547_1.6.0 -client -XX:UnlockInternalVMOptions=true -Dsun.java.launcher=SUN_STANDARD com.jrockit.mc.rcp.start.MCMain
java.home       : C:\jrockits\R28.0.0_R28.0.0-547_1.6.0\jre
j.class.path    : C:\jrockits\R28.0.0_R28.0.0-547_1.6.0/missioncontrol/mc.jar
j.lib.path : C:\jrockits\R28.0.0_R28.0.0-
...
StackOverFlow   : 0 StackOverFlowErrors have occured
OutOfMemory     : 0 OutOfMemoryErrors have occured
C Heap          : Good; no memory allocations have failed
GC Strategy     : Mode: pausetime, with strategy: singleconcon(basic strategy : singleconcon)
GC Status       : OC is not running. Last finished OC was OC#369.
Heap            : 0x10040000 - 0x17207000 (Size: 113 MB)
Compaction      : (no compaction area)
CompRefs        : References are 32-bit.

Loaded modules:
0000000000400000-000000000043afff C:\jrockits\R28.0.0_R28.0.0-547_1.6.0\bin\jrmc.exe
0000000077d30000-0000000077e56fff C:\Windows\system32\ntdll.dll
00000000763f0000-00000000764cbfff C:\Windows\system32\kernel32.dll
0000000077a30000-0000000077accfff C:\Windows\system32\USER32.dll
0000000077400000-000000007744afff C:\Windows\system32\GDI32.dll
0000000077ea0000-0000000077f65fff C:\Windows\system32\ADVAPI32.dll
...
00000000764e0000-00000000765a2fff C:\Windows\system32\RPCRT4.dll
000000006d3e0000-000000006d3fefff C:\jrockits\R28.0.0_R28.0.0-547_1.6.0\jre\bin\java.dll

输出内容与JVM状态相关,例如版本、锁、线程、路径、载入的模块和动态库等。

参见heap_diagnostics命令。

11.4.22 run_optfile (R27)

正如在第2章中介绍的,在可以在启动JVM时,通过指导文件为JVM优化管理器提供相关参数。此外,还可以在运行时通过run_optfile命令来动态添加相关参数,通过参数filename指定所需的指导文件。需要注意的是,R27和R28版本所支持的指导文件的格式有些区别。此外,对于R27版本来说,由于指导文件并没有正式的说明文档,因此可能只会在通过JRockit官方支持时才会用到它。

11.4.23 run_optfile (R28)

R28版本中的run_optfile命令可以接收多个参数,其中最重要的仍然是filename,用于指定指导文件。R28版本中,指导文件依旧没有正式说明文档,其具体格式可能会在后续的版本中发生变化。在第2章中,介绍了有关指导文件相关内容,只不过还不完整。

run_optfile命令还可以按指定策略重新编译指定的方法。

在下面的示例中,会按照优化编译策略,重新编译jav.util.ArrayList#get方法。

C:\>jrcmd 7736 run_optfile method=java.util.ArrayList.get*
  strategy=opt disass=false

11.4.24 runfinalization

该命令用于强制JVM执行java.lang.System#runFinalization方法,即提示运行时应该要运行某些对象的finalize方法了。

11.4.25 runsystemgc

该命令用于强制执行一次full gc。

强制执行垃圾回收是非常少见的案例,因为JVM本身可以决定什么时候该进行垃圾回收。如果用户干预这个过程,则反倒可能会降低执行性能。但在某些场景下,显式调用垃圾回收方法是有用处的。例如,通过详细的垃圾回收日志来查看内存使用和存活对象集。

使用该命令时,若不添加参数,则默认只会执行年轻代垃圾回收(nursery collection),而不会对堆做内存整理操作。若要触发一次full gc,则需要添加参数full=true。如下所示:

C:\>jrcmd 4748 runsystemgc full=true
4748:

该命令不会返回任何信息。

11.4.26 set_vmflag (R28)

该命令用于设置JVM参数。如下所示:

C:\>jrcmd 7772 set_vmflag flag=DumpOnCrash value=false
7772:

成功执行后,该命令不会返回任何信息。若是对只读参数执行写操作,会返回错误信息,如下所示:

C:\>jrcmd 7772 set_vmflag flag=DisableAttachMechanism value=true
7772:
Not a writeable flag "DisableAttachMechanism"

若想修改那些在运行时不可修改的JVM参数,需要在启动JVM时,通过类似-XX:<Flag>=<value>形式的语法来设置参数。

参见`list_vmflags命令。

11.4.27 start_flightrecording (R28)

start_flightrecording命令用于启动JFR记录任务,可以是持续性任务或计时任务。使用JROCKIT_HOME/jre/lib/jfr目标下的命名模板文件(JSON格式),可以对记录任务做具体配置。

C:\>jrcmd 7420 start_flightrecording name=MyRecording settings=jra.jfs duration=30s filename=my_recording.jfr.gz compress=true
7420:
Started recording 5

在上面的示例中,通过命令名,使用jra.jfs模板开启了一个持续30秒的记录任务,记录结束后,会在JROCKIT_HOME目录下,生成一个名为my_recording.jfr.gz`的、压缩过的记录文件。

使用check_flightrecording命令可以在记录开始后检查记录任务的执行情况:

C:\>jrcmd 7420 check_flightrecording
7420:
Recording : id=0 name="continuous" duration=0s (running)
Recording : id=5 name="MyRecording" duration=30s dest="my_recording.jfr.gz" compress=true (running)

在30秒过后,记录任务的状态会从running变为stopped,并生成记录文件。

有些模板只能是附加的,即它们必须和其他基础模板一起使用,这类模板在其文件开头的注释信息中做了说明。如果注释信息以 "Additional settings"开头,则说明它是附加模板。使用方式如下所示:

C:\>jrcmd 7420 start_flightrecording name=DefaultAndLocks settings=default.fls settings=lock.fls duration=30s filename=defaultAndLocks.jfr.gz compress=true

就操作JFR来说,最简单的方式还是使用JRockit Mission Control客户端。更多有关JFR的信息,请参见第9章的内容。

压缩文件可能会带来些额外的开销,但会降低文件大小。

参见check_flightrecording `dump_flightrecordingstop_flightrecording

11.4.28 start_management_server

该命令用于在没有启动脚本重启JVM的情况下,开启外部管理代理(external management agent)。其具体实现与使用-Xmanagement参数开启管理代理相同。

启动应用程序服务器,部署J2EE应用程序可能需要花费相当长的时间,而且JVM"热身"又需要花费一段时间,因此,若是在启动JVM忘记添加参数配置是很闹心的。如果是生产环境的服务器,重启就更麻烦了。

在下面的示例中,通过该命令在4711端口开启了一个外部管理代理,关闭了SSL和身份教研,开启了自动发现(JDP)。需要注意的是,这里提前配置好password.properties文件和密钥文件。更多详细内容,请参见Oracle Sun Developer Network中有关 Monitoring and Management Using JMX Technology的内容。

C:\>jrcmd 473528 start_management_server ssl=false authenticate=false port=4711 autodiscovery=true
2416:

该命令在执行成功后,不会返回任何信息。

start_management_server命令总是会启动一个本地管理代理(local management agent),而在开启本地代理之后,就不能被关闭了。

参见kill_management_server命令。

11.4.29 startjrarecording (R27)

操作JRA记录,最好是通过JRockit Mission Control客户端。更多有关这方面的信息,请参见第8章的内容.

不过在某些场景下,可能无法使用JRockit Mission Control客户端,例如环境不允许使用JMX连接,或者使用的JDK 1.4版本等等。这时,就该startjrarecording命令出场了。在下面的示例中,通过命令行在进程号5516的JRockit进程中开启了一个JRA记录任务,任务持续2分钟,在30秒之后开始记录。

在对使用了大量框架,或使用了企业容器(例如WebLogic)的应用程序做采样时,调用栈通常都很深。这时需要通过配置参数,来调整采样信息。

参数sampletime用于指定线程采样的频率。由于示例中采样的持续时间很短,因此将采样频率设置为5毫米一次。同时,开启对延迟事件的记录。

C:\>jrcmd 5516 startjrarecording filename=C:\myrecording.jra recordingtime=120 delay=30 tracedepth=64 sampletime=5 latency=true
5516:
JRA recording started.

开始执行命令后,JVM会在控制台开始打印如下相关内容:

[INFO ][jra ] Delaying JRA recording for 30 seconds.
[INFO ][jra ] Starting JRA recording with these options:
filename=D:\myrecording.jra, recordingtime=120s, methodsampling=1,
  gcsampling=1, heapstats=1, nativesamples=0, methodtraces=1,
  sampletime=5, zip=1, hwsampling=0 delay=30s, tracedepth=64
  threaddump=1, threaddumpinterval=0s, latency=1,
  latencythreshold=20ms, cpusamples=1, cpusampleinterval=1s

在记录结束后,JVM会打印类似下面的内容:

[INFO ][jra ] Zipped the recording file.
[INFO ][jra ] Finished recording. Results written to
C:\myrecording.jra.

参见命令checkjrarecordingstopjrarecording

11.4.30 stop_flightrecording (R28)

该命令用于终止进行中的JFR记录任务,目标任务可以通过参数namerecording来指定。如下所示:

C:\>jrcmd 7420 stop_flightrecording recording=10
7420:

默认情况下,会针对被终止的记录任务生成转储文件。如果不想保留记录数据,可以添参数discard=true。终止任务时,会将目标记录从check_flightrecording命令的输出列表中移除,因此可以使用该命令清理不再需要的记录任务。

参见命令check_flightrecording dump_flightrecordingstart_flightrecording

11.4.31 timestamp

该命令用于打印时间戳,并显示出JVM已经运行的持续时间。

C:\>jrcmd 6012 print_properties
6012:
==== Timestamp ==== uptime: 0 days, 00:04:39 time:
  Sun Jan 24 15:47:42 2010

11.4.32 verbosity

该命令用于控制JRockit中的日志模块,它可以针对某个子系统调整日志级别,重定向日志输出,以及调整日志输出内容。执行该命令时,若不添加额外参数,则会列出当前所有日志模块。

C:\demos_3.1>jrcmd 4504 verbosity
4504:
Current logstatus:
        jrockit : level=WARN, decorations=201, sanity=NONE
        memory (gc) : level=WARN, decorations=201, sanity=NONE
        nursery (yc) : level=WARN, decorations=201, sanity=NONE
        model : level=WARN, decorations=201, sanity=NONE
        devirtual : level=WARN, decorations=201, sanity=NONE
        codegen (code) : level=WARN, decorations=201, sanity=NONE
        native (jni) : level=WARN, decorations=201, sanity=NONE
        thread : level=WARN, decorations=201, sanity=NONE
        opt : level=WARN, decorations=201, sanity=NONE

具体输出内容中,每行的第一个单词是模块名,圆括号中的是模块的别名。

下面的示例中,启用了代码生成器模块(参见第2章内容)的常规输出,其具体效果,与启动JVM时添加-Xverbose:codegen参数相同。

C:\demos_3.1>jrcmd 5556 verbosity set=codegen=INFO
5556:
Current logstatus:
        jrockit : level=WARN, decorations=201, sanity=NONE
        memory (gc) : level=WARN, decorations=201, sanity=NONE
        nursery (yc) : level=WARN, decorations=201, sanity=NONE
        model : level=WARN, decorations=201, sanity=NONE
        devirtual : level=WARN, decorations=201, sanity=NONE
        codegen (code) : level=INFO, decorations=201, sanity=NONE

正如示例中所展现的,verbosity命令列出了新的日志状态。

verbosity命令还可用于做异常分析,找出异常是在何处抛出的。

在R28版本之前,那时JFR还不能做异常分析,唯一的方法就是查日志,在启动JVM时,添加参数-Xverbose:exceptions(参见第5章相关内容)。

下面的示例展示了如何开启/关闭异常分析,以及如何调整输出内容。若将参数decorations置空,则默认会调整时间戳、模块名和进程号的输出。

C:\>jrcmd 6064 verbosity set=exceptions=info decorations=module
6064:
Current logstatus:

之后,若目标JVM进程抛出异常,则会打印信息 "Throw me!"。

[excepti] ExceptionThrowerException: Throw me!
[excepti] ExceptionThrowerException: Throw me!

将日志级别设置为debug后,JRockit会显示出异常的调用栈:

D:\>jrcmd 6064 verbosity set=exceptions=debug decorations=module
6064:
Current logstatus:

其效果与启动JVM时添加-Xverbose:exceptions=debug相同:

[excepti] ExceptionThrowerException: Throw me!
  at jrockit/vm/Reflect.fillInStackTrace0(Ljava/lang/Throwable;)V(Native Method)
  at java/lang/Throwable.fillInStackTrace()Ljava/lang/Throwable;(Native Method)
  at java/lang/Throwable.<init>(Throwable.java:196)
  at java/lang/Exception.<init>(Exception.java:41)
  at ExceptionThrowerException.<init>(ExceptionThrowerException.java:5)
  at ExceptionThrower.throwMe(ExceptionThrower.java:24)
  at ExceptionThrower.doStuff(ExceptionThrower.java:20)
  at ExceptionThrower.loop(ExceptionThrower.java:11)
  at ExceptionThrower.main(ExceptionThrower.java:4)
  at jrockit/vm/RNI.c2java(IIIII)V(Native Method)
  --- End of stack trace

这样就可以在生产环境中队日志进行配置了。在异常分析完成后,可以将日志级别还原回原来的设置,不会产生额外的执行开销。

11.4.33 version

该命令用于在不重启应用程序服务器的情况下查看JRockit的具体版本。例如,已经将JRockit JVM注册为系统服务,没有控制台可用,就可以通过该命令查看JRockit JVM的具体版本信息。使用该命令时,无需添加额外参数。

C:\>%JAVA_HOME%\bin\jrcmd 2416 version
2416:
BEA JRockit(R) (build R27.6.2-20_o-108500-1.6.0_05-20090120-1116-windows-ia32, compiled mode)